#include "H264SliceHeader.hpp"
#include "H264CommonFunction.hpp"

void ref_pic_list_mvc_modification(){
    return
}

void SliceHeader::pred_weight_table(BitStream& bitstream){
    luma_log2_weight_denom = bitstream.ReadUE();
    chroma_log2_weight_denom = bitstream.ReadUE();
    for(int i = 0; i <= num_ref_idx_l0_active_minus1;i++){
        luma_weight_l0_flag = bitstream.ReadU1();
        if(luma_weight_l0_flag){
            luma_weight_l0[i] = bitstream.ReadSE();
            luma_offset_l0[i] = bitstream.ReadSE();
        }
        chroma_weight_l0_flag = bitstream.ReadU1();
        if(chroma_weight_l0_flag){
            for(int j = 0; j < 2;j++){
                chroma_weight_l0[i][j];
                chroma_offset_l0[i][j];
            }
        }
    }
    if(slice_type = B_SLICE){
        for(int i = 0; i <= num_ref_idx_l1_active_minus1; i++){
            luma_weight_l1_flag = bitstream.ReadU1();
            if(luma_weight_l0_flag){
                luma_weight_l1[i] = bitstream.ReadSE();
                luma_offset_l1[i] = bitstream.ReadSE();
            }
            chroma_weight_l1_flag = bitstream.ReadU1();
            if(chroma_weight_l1_flag){
                for(int j = 0; j < 2; j++){
                    chroma_weight_l1[i][j];
                    chroma_offset_l1[i][j];
                }
            }
        }
    }

    return;
}

//记录了当前帧的参考帧信息
void SliceHeader::ref_pic_list_modification(BitStream& bitstream){  
    if(slice_type % 5 != I_SLICE && slice_type % 5 != SI_SLICE){
        ref_pic_list_modification_flag_l0 = bitstream.ReadU1();
        if(ref_pic_list_modification_flag_l0){  //指明是否由重排序，对参考帧列表 RefPicList0 进行修改
            do{
                modification_of_pic_nums_idc = bitstream.ReadUE();
                //若 modification_of_pic_nums_idc 为 0 或 1，执行短期参考帧的修改过程
                if(modification_of_pic_nums_idc == 0 ||  modification_of_pic_nums_idc==1)
                    abs_diff_pic_num_minus1 = bitstream.ReadUE();
                else if(modification_of_pic_nums_idc == 2) 
                    long_term_pic_num = bitstream.ReadUE();

            }while(modification_of_pic_nums_idc != 3)  //==3,参考帧列表的修改过程完成
        }
    }
    if(slice_type % 5 == B_SLICE){
        ref_pic_list_modification_flag_l1 = bitstream.ReadU1();
        if(ref_pic_list_modification_flag_l1){
            do{
                modification_of_pic_nums_idc = bitstream.ReadUE();
                if(modification_of_pic_nums_idc == 0 ||  modification_of_pic_nums_idc==1)
                    abs_diff_pic_num_minus1 = bitstream.ReadUE();
                else if(modification_of_pic_nums_idc == 2)
                    long_term_pic_num = bitstream.ReadUE();
            }while(modification_of_pic_nums_idc != 3)
        }

    }

    return;
}

void SliceHeader::def_ref_pic_marking(BitStream& bitstream){
    if(nal_unit_type == 5){
        no_output_of_prior_pics_flag = bitstream.ReadU1();
        long_term_reference_flag = bitstream.ReadU1();
    }
    else{
        adaptive_ref_pic_marking_mode_flag = bitstream.ReadU1();
        if(adaptive_ref_pic_marking_mode_flag){
            do{
                memory_management_control_operation = bitstream.ReadUE();
                if(memory_management_control_operation == 1 || memory_management_control_operation == 3){
                    difference_of_pic_nums_minus1 = bitstream.ReadUE();
                }
                if(memory_management_control_operation == 2){
                    long_term_pic_num = bitstream.ReadUE();
                }
                if(memory_management_control_operation == 3 || memory_management_control_operation == 6){
                    long_term_frame_idx = bitstream.ReadUE();
                }
                if(memory_management_control_operation == 4){
                    max_long_term_frame_idx_plus1 = bitstream.ReadUE();
                }
            }while(memory_management_control_operation != 0)
        }
    }
    return;
}


int SliceHeader::Parse(NaluSPS (&msps)[H264_MAX_SPS_COUNT, NaluPPS (&mpps)[H264_MAX_PPS_COUNT]){
    BitStream bistream(rbsp.RBSPBuf+1,rbsp.len-1);
    
    first_mb_in_slice = bistream.ReadUE();
    slice_type = bistream.ReadUE() % 5;
    pic_parameter_id = bistream.ReadUE();
    
    NaluPPS pps = mpps[pic_parameter_id];
    NaluSPS sps = msps[pps.seq_parameter_set_id];

    if(sps.separate_colour_plane_flag == 1){
        colour_plane_id = bistream.ReadU(2);
    }
    frame_num = bistream.ReadU(sps.log2_max_frame_num_minus4+4);
    if(!sps.frame_mbs_only_flag){
        field_pic_flag = bistream.ReadU1();
        if(field_pic_flag){
            bottom_field_flag = bistream.ReadU1();
        }
    }
    if(IdrPicFlag){
        idr_pic_id = bistream.ReadUE();
    }
    if(sps.pic_order_cnt_type == 0){
        int v = sps.log2_max_pic_order_cnt_lsb_minus4 + 4;
        pic_order_cnt_lsb = bistream.ReadU(v);
        if(pps.bottom_field_pic_order_in_frame_present_flag && !field_pic_flag){
            delta_pic_order_cnt_bottom = bistream.ReadSE();
        }
    }
    if(sps.pic_order_cnt_type == 1 && !sps.delta_pic_order_always_zero_flag){
        delta_pic_order_cnt[0] = bistream.ReadSE();
        if(pps.bottom_field_pic_order_in_frame_present_flag && !field_pic_flag){
            delta_pic_order_cnt[1] = bistream.ReadSE();
        }
    }

    if(pps.redundant_pic_cnt_present_flag){
        redundant_pic_cnt = bistream.ReadUE();
    }
    if(slice_type == B_SLICE){
        direct_spatial_mv_pred_flag = bistream.ReadU1();
    }
    if(slice_type == P_SLICE || slice_type == SP_SLICE || slice_type == B_SLICE){
        num_ref_idx_active_override_flag = bistream.ReadU1();
        if(num_ref_idx_active_override_flag){
            num_ref_idx_l0_active_minus1 = bistream.ReadUE();
            if(slice_type == B_SLICE){
                num_ref_idx_l1_active_minus1 = bistream.ReadUE();
            }
        }
    }

    if(nal_unit_type == H264_NAL_EXTEN_SLICE){
        ref_pic_list_mvc_modification();
    }
    else{
        ref_pic_list_modification(bistream); 
    }

    if(pps.weighted_pred_flag){  //表示在P/SP slice中是否开启加权预测
        pred_weight_table(bistream);
    }

    if(nal_ref_idc != 0){
        def_ref_pic_marking(bistream);
    }

    if(pps.entropy_coding_mode_flag && slice_type != I_SLICE && slice_type != SI_SLICE){
        cabac_init_idc = bistream.ReadUE();
    }
    slice_qp_delta = bistream.ReadSE();
    if(slice_type == SP || slice_type == SI){
        if(slice_type == SP){
            sp_for_switch_flag = bistream.ReadU1();
        }
        slice_qs_delata = bistream.ReadSE();
    }
    if(pps.deblocking_filter_control_present_flag){
        disable_deblocking_filter_idc = bistream.ReadUE();
        if(disable_deblocking_filter_idc != 1){
            slice_alpha_c0_offset_div2 = bistream.ReadSE();
            slice_beta_offset_div2 = bistream.ReadSE();
        }
    }
    if(pps.num_slice_groups_minus1 > 0 && pps.slice_group_map_type >=3 && pps.slice_group_map_type <= 5){
        int v = h264_log2(pps.PicSizeInMapUnits/pps.SliceGroupChangeRate+1);
        slice_group_change_cycle = bistream.ReadU(v); 
    }


}